#include <algorithm>
#include <cstdio>
#include <queue>
#include <vector>

const int N = 10, M = 305, dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};

struct Block {
  int a[N][N];
  inline bool operator<(const Block &rhs) const {
    for (int i = 1; i < N; i++)
      for (int j = 1; j < N; j++)
        if (a[i][j] != rhs.a[i][j]) return a[i][j] < rhs.a[i][j];
    return 0;
  }
} ans[M];

struct Node {
  int x, y;
  Node(int x, int y) : x(x), y(y) {}
};

std::vector<Node> uni[N * N];
std::vector<int> p[N * N];
std::queue<Node> q;
int map[N][N], a[N][N], n, cnt, tot;
bool vis[N][N], visrow[N][N], viscol[N][N];

inline int fact(const int &x) {
  int res = 1, copy_x;
  for (int i = 2, tmp; i * i <= x; i++) {
    if (copy_x % i == 0) {
      tmp = 0;
      while (copy_x % i == 0) { copy_x /= i, tmp++; }
      res *= (tmp + 1);
    }
  }
  if (copy_x != 1) res <<= 1;
  return res;
}

inline void divide(int id, int x) {
  for (int i = 1; i <= n; i++)
    if (x % i == 0) p[id].push_back(i);
}

inline void bfs(const int &i, const int &j) {
  vis[i][j] = true;
  q.emplace(i, j);
  while (!q.empty()) {
    int x = q.front().x, y = q.front().y;
    q.pop();
    uni[cnt].emplace_back(x, y);
    for (int k = 0, tx, ty; k < 4; k++) {
      tx = x + dx[k], ty = y + dy[k];
      if (!vis[tx][ty] && map[tx][ty] == map[x][y]) {
        vis[tx][ty] = true;
        q.push(Node(tx, ty));
      }
    }
  }
}

void solve(int dep);

void fillblock(int id, int step, int prod, int sum) {
  if (step > sum) solve(id + 1);
  else {
    int x = uni[id][step].x, y = uni[id][step].y;
    for (auto &u : p[id]) {
      if ((prod == u || step < sum) && prod % u == 0 && !visrow[x][u] && !viscol[y][u]) {
        visrow[x][u] = true, viscol[y][u] = true;
        a[x][y] = u;
        fillblock(id, step + 1, prod / u, sum);
        // a[x][y] = 0;
        visrow[x][u] = false, viscol[y][u] = false;
      }
    }
  }
}

void solve(int step) {
  if (step > cnt) {
    ++tot;
    for (int i = 1; i <= n; i++)
      for (int j = 1; j <= n; j++) ans[tot].a[i][j] = a[i][j];
  } else {
    fillblock(step, 1, uni[step].begin()->x, uni[step].size() - 1);
  }
}

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("testdata.in", "r", stdin);
  freopen("testdata.out", "w", stdout);
#else
  freopen("kenken.in", "r", stdin);
  freopen("kenken.out", "w", stdout);
#endif
#endif

  scanf("%d", &n);
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) scanf("%d", &map[i][j]);
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
      if (!vis[i][j]) {
        uni[++cnt].emplace_back(map[i][j], 0);
        bfs(i, j);
      }

  std::sort(uni + 1, uni + cnt + 1,
            [](const std::vector<Node> &lhs, const std::vector<Node> &rhs) {
              if (lhs.size() == rhs.size()) return fact(lhs[0].x) <= fact(rhs[0].x);
              return lhs.size() < rhs.size();
            });

  for (int i = 1; i <= cnt; i++) divide(i, uni[i].begin()->x);
  solve(1);
  printf("%d\n", tot);
  Block tmp = ans[1];
  for (int i = 2; i <= tot; i++) tmp = std::min(tmp, ans[i]);
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) printf("%d ", tmp.a[i][j]);
    putchar('\n');
  }
  return 0;
}